﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ProjectenArtesis.Web;
using System.Collections.Generic;
using System.ServiceModel.DomainServices.Client;
using System.Linq;

namespace ProjectenArtesis
{
    public class OlodStructuur : IComparable
    {
        public Item HoofdOlod { get; set; }
        public List<Item> DeelOlods { get; set; }

        #region Constructors
        public OlodStructuur()
        {
            HoofdOlod = null;
            DeelOlods = new List<Item>();
        }
        public OlodStructuur(Item hoofdOlod, List<Item> deelOlods)
        {
            HoofdOlod = hoofdOlod;
            DeelOlods = deelOlods;
        }
        #endregion

        public override string ToString()
        {
            return HoofdOlod.Name;
        }

        public int CompareTo(object obj)
        {
            if (obj.GetType().Equals(this.GetType()))
            {
                OlodStructuur anderObject = (OlodStructuur)obj;
                return this.HoofdOlod.Name.CompareTo(anderObject.HoofdOlod.Name);
            }
            throw new ArgumentException("Fout type in CompareTo() -- moeten 2 OlodStructuur-objecten zijn!");
        }

        public void StudiepuntenCorrigeren()
        {
            // studiepunten berekenen voor de structuur.hoofdolod
            // als er geen deelolods zijn, zit de juiste waarde normaalgezien reeds in het hoofdolod-element
            if (this.DeelOlods.Count > 0)
            {
                int studiepuntenHoofdOlod = 0;
                Item[] deelolods = this.DeelOlods.ToArray();
                for (int i = 0; i < deelolods.GetLength(0); i++)
                {
                    studiepuntenHoofdOlod += (int)deelolods[i].Studiepunten;
                }
                this.HoofdOlod.Studiepunten = studiepuntenHoofdOlod;
            }
        }

        public int ExtractNumberFromHoofdOlodName()
        {
            int positie = 0;
            bool gevonden = false;
            int nummer = 0; // standaard hoort het bij 'semester 0'; en worden dus vakken zonder nummer in vooraan opgelijst
            while ((!gevonden) && (positie < this.HoofdOlod.Name.Length))
            {
                gevonden = int.TryParse(this.HoofdOlod.Name[positie].ToString(), out nummer);
                positie++;
            }
            return nummer;
        }

        private static List<OlodStructuur> GenerateStructuren(List<Item> items)
        {
            // groeperen per opleidingsonderdeel
            List<OlodStructuur> olodstructuren = new List<OlodStructuur>();
            // eerste de hoofd-olods creëren, anders kan het zijn dat DOLODs al voorkomen in de lijst, terwijl de lijst voor hoofdOLODs nog niet volledig is
            foreach (var item in items)
            {
                if (item.ParentId == null)
                {
                    OlodStructuur structuur = new OlodStructuur();
                    structuur.HoofdOlod = item;
                    olodstructuren.Add(structuur);
                }
            }
            // deel-olods toevoegen aan de lijst met hoofdolods
            foreach (var item in items)
            {
                foreach (var structuur in olodstructuren)
                {
                    if (structuur.HoofdOlod.Id.Equals(item.ParentId))
                    {
                        item.Name = item.Name.Split(':')[1].Trim();
                        structuur.DeelOlods.Add(item);
                    }
                }
            }

            List<List<OlodStructuur>> lijstenOlodstructurenPerSemester = new List<List<OlodStructuur>>();
            // deze variabele bevat lijsten van olodstructuren. Olodstructuren bevatten op hun beurt weer een hoofdolod en een lijst van deelolods
            foreach (var structuur in olodstructuren)
            {
                structuur.StudiepuntenCorrigeren();

                int nummerSemester = structuur.ExtractNumberFromHoofdOlodName();
                bool lijstReedsAanwezig = false;
                foreach (var semesterlijst in lijstenOlodstructurenPerSemester)
                {
                    // eerste lijst bevat steeds SEMESTERNUMMER
                    if (semesterlijst.ToArray()[0].HoofdOlod.Id.Equals(nummerSemester))
                    {
                        lijstReedsAanwezig = true;
                        semesterlijst.Add(structuur);
                    }
                }
                if (!lijstReedsAanwezig)
                {
                    OlodStructuur idStructuur = new OlodStructuur();
                    idStructuur.HoofdOlod = (new Item() { Id = nummerSemester });
                    List<OlodStructuur> eersteLijstInSemesterlijst = new List<OlodStructuur>();
                    eersteLijstInSemesterlijst.Add(idStructuur);
                    eersteLijstInSemesterlijst.Add(structuur);
                    lijstenOlodstructurenPerSemester.Add(eersteLijstInSemesterlijst);
                }

            }

            List<OlodStructuur> geordendeOlodLijst = new List<OlodStructuur>();
            // overbodige subelementen uit elke sublijst weer verwijderen, en toevoegen aan de uiteindelijke lijst
            foreach (var semesterlijst in lijstenOlodstructurenPerSemester)
            {
                semesterlijst.RemoveAt(0);
                semesterlijst.Sort(); // alfabetisch sorteren -- CompareTo() nodig in klasse Olodstructuur
                foreach (var structuur in semesterlijst)
                {
                    geordendeOlodLijst.Add(structuur);
                }
            }

            return geordendeOlodLijst;
        }

        public static void MakeOrderedOlodStructuur(ArtesisDomainContext cl, EntityQuery<Item> olodQuery, MainPage hoofdpagina)
        {
            List<Item> items = new List<Item>();
            var result = cl.Load<Item>(olodQuery, (olods) =>
            {
                foreach (var olod in olods.Entities)
	            {
                    items.Add(new Item() { Id = olod.Id, Name = olod.Name, 
                        ParentId = olod.ParentId, Studiepunten = olod.Studiepunten });
	            }
                List<OlodStructuur> structuren = GenerateStructuren(items);
                hoofdpagina.GenerateOlodView(structuren);
            }, true);

           
        }
    }
}
